﻿#include "ssResMesh.h"
#include "file/ssReadFile.h"
#include "console/ssConsole.h"
#include "string/ssStrfunc.h"

namespace StarSeeker
{

ssResMesh::ssResMesh()
{
	m_vertexArr.Init(9);
	m_texCoordArr.Init(6);
	m_normalArr.Init(9);
	m_tangentArr.Init(9);
	m_indexArr.Init(3);
	m_colorArr.Init(9);
}

bool ssResMesh::ReadObjexFromFile( const char* uri )
{
	ssReadFile rf;
	rf.SetPath(uri);
	if (rf.OpenFile(false))
	{
		const char* pLine = 0;
		ssfloat val[3] = {0};
		u16 vi[9] = {0};
		while (rf.GetLine(0, 0))
		{
			pLine = rf.GetBuffer().Buf();
			if (pLine[0]=='v' && pLine[1]==' ')
			{
				u32 beg = 0;
				u32 sz = strlen(pLine);
				for (u32 i=1; i<sz; ++i)
				{
					if (i!=' ')
					{
						beg = i;
						break;
					}
				}
				if (beg)
				{
					sscanf(pLine+beg, "%f %f %f", val, val+1, val+2);
					m_vertexArr.PushBack(val[0]);
					m_vertexArr.PushBack(val[1]);
					m_vertexArr.PushBack(val[2]);
				}
			}
			else if (pLine[0]=='v' && pLine[1]=='t')
			{
				u32 beg = 0;
				u32 sz = strlen(pLine);
				for (u32 i=2; i<sz; ++i)
				{
					if (i!=' ')
					{
						beg = i;
						break;
					}
				}
				if (beg)
				{
					sscanf(pLine+beg, "%f %f %f", val, val+1, val+2);
					m_texCoordArr.PushBack(val[0]);
					val[1] = 1.0f - val[1];
					m_texCoordArr.PushBack(val[1]);
				}
			}
			else if (pLine[0]=='v' && pLine[1]=='n')
			{
				u32 beg = 0;
				u32 sz = strlen(pLine);
				for (u32 i=2; i<sz; ++i)
				{
					if (i!=' ')
					{
						beg = i;
						break;
					}
				}
				if (beg)
				{
					sscanf(pLine+beg, "%f %f %f", val, val+1, val+2);
					m_normalArr.PushBack(val[0]);
					m_normalArr.PushBack(val[1]);
					m_normalArr.PushBack(val[2]);
				}
			}
			else if (pLine[0] == 't' && pLine[1] == 'g')
			{
				u32 beg = 0;
				u32 sz = strlen(pLine);
				for (u32 i = 2; i < sz; ++i)
				{
					if (i != ' ')
					{
						beg = i;
						break;
					}
				}
				if (beg)
				{
					sscanf(pLine + beg, "%f %f %f", val, val + 1, val + 2);
					m_tangentArr.PushBack(val[0]);
					m_tangentArr.PushBack(val[1]);
					m_tangentArr.PushBack(val[2]);
				}
			}
			else if (pLine[0]=='f' && pLine[1]==' ')
			{
				sscanf(pLine, "f %hd/%hd/%hd %hd/%hd/%hd %hd/%hd/%hd", vi, vi+1, vi+2, vi+3, vi+4, vi+5, vi+6, vi+7, vi+8);
				m_indexArr.PushBack(--vi[0]);
				m_indexArr.PushBack(--vi[3]);
				m_indexArr.PushBack(--vi[6]);
			}
		}

		//CreateVertex(vertexArr.Memory(), vertexArr.Count());
		//CreateIndex(SS_INDEX_16, indexArr.Memory(), indexArr.Count());
		//CreateTexture2d(texCoordArr.Memory(), texCoordArr.Count());
		//CreateNormal(normalArr.Memory(), normalArr.Count());
		//CreateTangent(tangentArr.Memory(), tangentArr.Count());
		return true;
	}
	SS_CONSOLE->Printf("objex open file error:%s\n", uri);
	return false;
}

bool ssResMesh::ReadObjFromFile( const char* uri )
{
	ssReadFile rf;
	rf.SetPath(uri);
	if (rf.OpenFile(false))
	{
		const char* pLine = 0;
		ssfloat val[3] = {0};
		//uidx vi[9] = {0};
		ssArray<F2_s> vt;
		vt.Init(6);
		ssArray<I33_s> index;
		index.Init(9);
		while (rf.GetLine(0, 0))
		{
			pLine = rf.GetBuffer().Buf();
			if (pLine[0]=='v' && pLine[1]==' ')
			{
				u32 beg = 0;
				u32 sz = strlen(pLine);
				for (u32 i=1; i<sz; ++i)
				{
					if (i!=' ')
					{
						beg = i;
						break;
					}
				}
				if (beg)
				{
					sscanf(pLine+beg, "%f %f %f", val, val+1, val+2);
					m_vertexArr.PushBack(val[0]);
					m_vertexArr.PushBack(val[1]);
					m_vertexArr.PushBack(val[2]);
				}
			}
			else if (pLine[0]=='v' && pLine[1]=='t')
			{
				u32 beg = 0;
				u32 sz = strlen(pLine);
				for (u32 i=2; i<sz; ++i)
				{
					if (i!=' ')
					{
						beg = i;
						break;
					}
				}
				if (beg)
				{
					F2_s tmp;
					sscanf(pLine+beg, "%f %f %f", val, val+1, val+2);
					tmp.f2[0] = val[0];
					tmp.f2[1] = 1.0f - val[1];
					vt.PushBack(tmp);
				}
			}
			else if (pLine[0]=='v' && pLine[1]=='n')
			{
				u32 beg = 0;
				u32 sz = strlen(pLine);
				for (u32 i=2; i<sz; ++i)
				{
					if (i!=' ')
					{
						beg = i;
						break;
					}
				}
				if (beg)
				{
					sscanf(pLine+beg, "%f %f %f", val, val+1, val+2);
					m_normalArr.PushBack(val[0]);
					m_normalArr.PushBack(val[1]);
					m_normalArr.PushBack(val[2]);
				}
			}
			else if (pLine[0]=='f' && pLine[1]==' ')
			{
				I33_s tmp33 = {0};
				if (vt.Count()>0 && m_normalArr.Count()>0)
				{
					sscanf(pLine, "f %hd/%hd/%hd %hd/%hd/%hd %hd/%hd/%hd", &tmp33.i33[0][0], &tmp33.i33[0][1], &tmp33.i33[0][2], &tmp33.i33[1][0], &tmp33.i33[1][1], &tmp33.i33[1][2], &tmp33.i33[2][0], &tmp33.i33[2][1], &tmp33.i33[2][2]);
				}
				else if (vt.Count()>0)
				{
					sscanf(pLine, "f %hd/%hd %hd/%hd %hd/%hd", &tmp33.i33[0][0], &tmp33.i33[0][1], &tmp33.i33[1][0], &tmp33.i33[1][1], &tmp33.i33[2][0], &tmp33.i33[2][1]);
				}
				else if (m_normalArr.Count()>0)
				{
					sscanf(pLine, "f %hd//%hd %hd//%hd %hd//%hd", &tmp33.i33[0][0], &tmp33.i33[0][2], &tmp33.i33[1][0], &tmp33.i33[1][2], &tmp33.i33[2][0], &tmp33.i33[2][2]);
				}
				else
				{
					sscanf(pLine, "f %hd %hd %hd", &tmp33.i33[0][0], &tmp33.i33[1][0], &tmp33.i33[2][0]);
				}
				index.PushBack(tmp33);
			}
		}
		for (u32 i=0; i<index.Count(); ++i)
		{
			m_indexArr.PushBack(--index[i].i33[0][0]);
			m_indexArr.PushBack(--index[i].i33[1][0]);
			m_indexArr.PushBack(--index[i].i33[2][0]);
			if (vt.Count()>0)
			{
				m_texCoordArr.Init(m_vertexArr.Count());
				m_texCoordArr[index[i].i33[0][0]*2] = vt[index[i].i33[0][1]-1].f2[0];
				m_texCoordArr[index[i].i33[0][0]*2+1] = vt[index[i].i33[0][1]-1].f2[1];
				m_texCoordArr[index[i].i33[1][0]*2] = vt[index[i].i33[1][1]-1].f2[0];
				m_texCoordArr[index[i].i33[1][0]*2+1] = vt[index[i].i33[1][1]-1].f2[1];
				m_texCoordArr[index[i].i33[2][0]*2] = vt[index[i].i33[2][1]-1].f2[0];
				m_texCoordArr[index[i].i33[2][0]*2+1] = vt[index[i].i33[2][1]-1].f2[1];
			}
		}

		//CreateVertex(vertexArr.Memory(), vertexArr.Count());
		//CreateIndex(SS_INDEX_16, indexArr.Memory(), indexArr.Count());
		//CreateTexture2d(texCoordArr.Memory(), texCoordArr.Count());
		//CreateNormal(normalArr.Memory(), normalArr.Count());
		return true;
	}
	SS_CONSOLE->Printf("obj open file error:%s\n", uri);
	return false;
}

bool ssResMesh::LoadFromFile(const char* uri)
{
	u32 len = StrLen(uri);
	if (uri && len>3)
	{
		if (uri[len-3]=='o' && uri[len - 2] == 'b' && uri[len - 1] == 'j')
		{
			return ReadObjFromFile(uri);
		}
		else if (uri[len - 5] == 'O' && uri[len - 4] == 'B' && uri[len - 3] == 'J' && uri[len - 2] == 'E' && uri[len - 1] == 'X')
		{
			return ReadObjexFromFile(uri);
		}
	}
	return false;
}

}
